package com.licode.codekit.buildprj;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.licode.codekit.utils.CheckUtil;
import com.licode.codekit.utils.UIBuilderUtil;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * @author licode
 */
public class ProjectUiBuilder {
    public static int DEFAULT_WID = 460;
    private final ProjectBuilder pb = new ProjectBuilder();
    private final JPanel north = new JPanel();
    private final JPanel center = new JPanel();
    private final JLabel prjDir = new JLabel("项目路径：", 4);
    private final JTextField prjDirContent = new JTextField();
    private final JLabel artifactIdName = new JLabel("artifact-id：", 4);
    private final JTextField artifactIdContent = new JTextField();
    private final JLabel groupIdName = new JLabel("group-id：", 4);
    private final JTextField groupIdContent = new JTextField();

    private final JLabel authorName = new JLabel("author：", 4);
    private final JTextField authorContent = new JTextField("licode");

    private final JLabel moduleName = new JLabel("模块名称：", 4);
    private final JTextField moduleContent = new JTextField();

    private final JLabel mdList = new JLabel("模块列表：", 4);
    private final ComboBox<String> mdListContent = new ComboBox<>();

    private final JLabel sbList = new JLabel("Spring Boot：", 4);
    private final ComboBox<String> sbListContent = new ComboBox<>();

    private final JButton buildOpenBtn = this.buildButton("选择目录");
    private final JButton buildPrjBtn = this.buildButton("创建项目");

    private final UIBuilderUtil uiBuilder = new UIBuilderUtil(120);

    private final ProjectContext projectCtx = new ProjectContext(CodeKitConf.PROJECT_TYPE);

    public ProjectUiBuilder() {
    }

    public JPanel initNorth() {
        JLabel title = new JLabel("小码咨询代码自动生成");
        title.setFont(new Font("微软雅黑", 0, 16));
        title.setHorizontalAlignment(2);
        title.setVerticalAlignment(0);
        // this.north.add(title);
        return this.north;
    }

    private void initModuleInfo(Project project) {
        String pomFile = project.getBasePath() + "/pom.xml";
        ProjectContext prjCtx = new ProjectContext(CodeKitConf.PROJECT_TYPE);

        if (!new File(pomFile).isFile()) {
            pb.setPrjExist(false);
            return;
        }

        if (!prjCtx.parse(pomFile)) {
            this.prjDirContent.setText(project.getBasePath());
            this.groupIdContent.setText(prjCtx.getGroupId());
            this.artifactIdContent.setText(prjCtx.getArtifactId());

            pb.setPrjExist(true);
            pb.setModules(prjCtx.getModules() == null ? new HashSet<>() : prjCtx.getModules());

            this.initModuleComBox();
        }
    }

    public JComponent initCenter(Project project, DialogWrapper dialogWrapper) {
        int defWidth = 480;
        this.center.setLayout(new GridLayout(0, 1));
        JButton dirBtn = this.buildButton("打开");

        this.prjDirContent.setPreferredSize(new Dimension(DEFAULT_WID, 0));

        this.center.add(uiBuilder.buildRow(this.prjDir, this.prjDirContent, dirBtn));
        this.center.add(this.buildRow(this.groupIdName, this.groupIdContent, defWidth));
        this.center.add(this.buildRow(this.artifactIdName, this.artifactIdContent, defWidth));

        this.center.add(this.buildRow(this.authorName, this.authorContent, defWidth));
        this.center.add(this.buildRow(this.sbList, this.sbListContent, defWidth));

        this.center.add(this.buildPrjModuleBtn(project, dialogWrapper));

        dirBtn.addActionListener((e) -> {
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            if (!StringUtil.isEmpty(this.prjDirContent.getText())) {
                fileChooser.setCurrentDirectory(new File(this.prjDirContent.getText()));
            }
            int option = fileChooser.showOpenDialog(this.center);
            if (option == 0) {
                File file = fileChooser.getSelectedFile();
                this.prjDirContent.setText(file.getAbsolutePath());
                this.checkProject(project, false);
            }
        });

        sbListContent.setEditable(false);
        sbListContent.addItem("2.3.12.RELEASE");
        sbListContent.addItem("3.2.6");
        sbListContent.setSelectedIndex(0);

        sbListContent.addItemListener(e -> {
            if (e.getItem() instanceof String) {
                if ("3.2.6".equals(e.getItem().toString())) {
                    projectCtx.setSpringBoot2x(false);
                    projectCtx.setJdkVersion(17);
                } else {
                    projectCtx.setSpringBoot2x(true);
                    projectCtx.setJdkVersion(8);
                }
            }
        });

        initModuleInfo(project);
        initPrjDirListener(project);

        return this.center;
    }

    private void initPrjDirListener(final Project project) {
        Document document = this.prjDirContent.getDocument();
        document.addDocumentListener(new DocumentListener() {
            public void insertUpdate(DocumentEvent e) {
                resetData();
            }

            public void removeUpdate(DocumentEvent e) {
                resetData();
            }

            public void changedUpdate(DocumentEvent e) {
                resetData();
            }
        });
    }

    private void resetData() {
        // this.artifactIdContent.setText("");
        this.groupIdContent.setText("");
        this.moduleContent.setText("");
        this.mdListContent.removeAllItems();

        this.pb.getModules().clear();
        this.pb.reset();
    }

    /**
     * 检测工程是否存在
     * @param project 工程对象
     * @return true
     */
    private boolean checkProject(Project project, boolean onlyCheck) {
        this.artifactIdContent.setText("");
        this.groupIdContent.setText("");
        this.mdListContent.removeAllItems();

        if (StringUtil.isEmpty(this.prjDirContent.getText())) {
            return false;
        } else {
            String errMsg = this.pb.setAndCheckProjectDir(this.prjDirContent.getText());
            this.initModuleComBox();

            if (StringUtil.isNotEmpty(errMsg)) {
                this.prjDirContent.setText("");
                this.buildPrjBtn.setEnabled(true);
                if (onlyCheck) {
                    Messages.showMessageDialog(project, errMsg,
                            "温馨提示", Messages.getInformationIcon());
                }
                return false;
            } else {
                if (this.pb.isEmptyDir()) {
                    if (onlyCheck) {
                        Messages.showMessageDialog(project,
                                "目录为空，请创建工程！", "温馨提示",
                                Messages.getInformationIcon());
                    }
                    return false;
                }
                return true;
            }
        }
    }

    private void initModuleComBox() {
        if (null != this.pb.getModules()) {
            Set<String> mdNames = this.pb.getModules();
            ComboBox<String> comboBox = this.mdListContent;
            Objects.requireNonNull(comboBox);
            mdNames.forEach(comboBox::addItem);
        }
    }

    private boolean createPrj(Project project) throws IOException {
        prjDirContent.updateUI();

        String pDir = this.prjDirContent.getText();
        String artifactId = this.artifactIdContent.getText();
        String groupId = this.groupIdContent.getText();
        String moduleName = this.moduleContent.getText();
        String author = this.authorContent.getText();

        if (StringUtil.isEmpty(pDir)) {
            Messages.showMessageDialog(project, "请输入工程目录",
                    "温馨提示", Messages.getInformationIcon());
        } else if (StringUtil.isEmpty(groupId)) {
            Messages.showMessageDialog(project, "请输入group-id",
                    "温馨提示", Messages.getInformationIcon());
        } else if (!CheckUtil.checkGroupId(groupId)) {
            Messages.showMessageDialog(project, "请输入合法的group-id",
                    "温馨提示", Messages.getInformationIcon());
        } else if (StringUtil.isEmpty(artifactId)) {
            Messages.showMessageDialog(project, "请输入artifact-id",
                    "温馨提示", Messages.getInformationIcon());
        }else if (!CheckUtil.checkStr(artifactId)) {
            Messages.showMessageDialog(project, "请输入合法的artifact-id",
                    "温馨提示", Messages.getInformationIcon());
        } else {
            projectCtx.setRootDir(pDir);
            projectCtx.setCurrentDir(pDir);
            projectCtx.setGroupId(groupId);
            projectCtx.setArtifactId(artifactId);

            if (StringUtil.isEmpty(author)) {
                projectCtx.setAuthor("licode");
            } else {
                projectCtx.setAuthor(author);
            }

            if (pb.isPrjExist()) {
                Messages.showMessageDialog(project, "目录不为空，请重新选择！",
                        "温馨提示", Messages.getInformationIcon());
                return false;
            } else {
                this.pb.createPrj(projectCtx);
                return true;
            }
        }

        return false;
    }

    private JComponent buildRow(Component left, Component right, int rWidth) {
        right.setMinimumSize(new Dimension(rWidth, 0));
        return uiBuilder.buildFillRow(left, right);
    }

    private JComponent buildPrjModuleBtn(Project project, DialogWrapper dialogWrapper) {
        FlowLayout fl = new FlowLayout();
        JPanel panel = new JPanel(fl);
        JButton cancel = this.buildButton("退出");
        fl.setAlignment(2);
        // panel.add(this.buildOpenBtn);
        panel.add(this.buildPrjBtn);
        panel.add(cancel);
        this.buildOpenBtn.addActionListener((e) -> {
            try {
                this.checkProject(project, false);
            } catch (Exception ignore) {
                Messages.showMessageDialog(project, "检测项目失败！",
                        "温馨提示", Messages.getInformationIcon());
            }
        });
        cancel.addActionListener((e) -> {
            dialogWrapper.close(0);
        });

        this.buildPrjBtn.addActionListener((e) -> {
            if (!this.pb.isNeedInit() || this.checkProject(project, true)) {
                this.createProjectOrModule(project, dialogWrapper);
            }
        });

        return panel;
    }

    private void createProjectOrModule(Project project, DialogWrapper dialogWrapper) {
        try {
            if (this.createPrj(project)) {
                Messages.showMessageDialog(project, "创建项目成功！",
                        "温馨提示", Messages.getInformationIcon());
                dialogWrapper.close(0);
            }
        } catch (Exception ignore) {
            Messages.showMessageDialog(project, "创建项目失败！",
                    "温馨提示", Messages.getInformationIcon());
        }
    }

    private JButton buildButton(String text) {
        JButton submit = new JButton(text);
        submit.setHorizontalAlignment(0);
        submit.setVerticalAlignment(0);
        return submit;
    }
}
